import os, sys, time
import threading, Queue
import subprocess
from threading import *
from subprocess import PIPE

from ivic.webfarm.WorkNode import *
from ivic.core import Logging
logger = Logging.get_logger('ivic.webfarm.Monitor')

class DataCollector(threading.Thread):
    
    def __init__(self):
        threading.Thread.__init__(self)
        self.data = Queue.Queue()
        self.running = True
        
    def collect(self):
        try:
            #execute the collecting data
            command = 'ipvsadm -ln'
            proc = subprocess.Popen(command, close_fds=True, shell=True, stdout=PIPE)
            proc.wait()
            output = proc.communicate()[0].split('\n')
            
            #data collection and extraction.
            info_dict = {}
            # no active nodes
            if len(output) < 5: return info_dict
            # parse active nodes
            for each in output[4:]:
                if len(each) < 5: continue
                try:
                    pieces = each.split()
                    if len(pieces) < 5: continue
                    
                    ip = pieces[1].split(':')[0]
                    weight = float(pieces[3])
                    conn = int(pieces[4])
                    neg_conn = int(pieces[5])
                    data = {'conn':conn, 'neg_conn':neg_conn, 'weight':weight}
                    info_dict[ip] = data
                except Exception, ex:
                    logger.error("%s:%s" % (sys._getframe().f_code.co_name, ex))        
            
            #returning the collected data 
            #logger.debug(info_dict)       
            return info_dict   
        except Exception, ex:
            logger.error("%s:%s" % (sys._getframe().f_code.co_name, ex))
            return None

    def run(self):
        try:
            while self.running:
                try:
                    data = self.collect()
                    if not data is None: self.data.put(data)
                except Exception, ex:
                    logger.error("%s:%s" % (sys._getframe().f_code.co_name, ex))
                    pass
                time.sleep(1)
        except Exception, ex:
            logger.error("%s:%s" % (sys._getframe().f_code.co_name, ex))
      
    def stop(self):
        self.running = False  
                    
class DataReporter(threading.Thread):
    
    def __init__(self, nodes_mgr, url):
        threading.Thread.__init__(self)
        self.nodesmgr = nodes_mgr
        self.url = url or ""
        self.running = True
        
    def curl_report(self, message, url):
        try:
            command = "curl -X POST -d \"%s\" -H \"Accept: text/xml\" %s" 
            command = command % (message, url)
            proc = subprocess.Popen(command, close_fds=True, shell=True)
            proc.wait()
            #logging the report event here
            logger.debug(command)
        except Exception, ex:
            logger.error("%s:%s" % (sys._getframe().f_code.co_name, ex))
        
    def run(self):
        try:
            while self.running:
                try:
                    message = self.nodesmgr.data.get()
                    url = self.url
                    self.curl_report(message, url)
                except Exception, ex:
                    logger.error("%s:%s" % (sys._getframe().f_code.co_name, ex))
                    pass
                time.sleep(6)
        except Exception, ex:
            logger.error("%s:%s" % (sys._getframe().f_code.co_name, ex))    
            
    def stop(self):
        self.running = False

class Monitor(threading.Thread):
    
    def __init__(self, nodes_mgr, url="http://www.portal.ivic.org.cn/"):
        threading.Thread.__init__(self)
        self.counter = 1 # take care: we count from 1.^-^
        self.nodesmgr = nodes_mgr
        self.collector = DataCollector()
        self.reporter = DataReporter(self.nodesmgr, url)
        self.running = True

    def run(self):
        try:
            self.collector.start()
            self.reporter.start()
            
            while self.running:
                try:
                    data = self.collector.data.get()
                    ret = self.nodesmgr.update_data(data)
                    if ret:
                        self.counter += 1
                        if self.counter % 7 == 0:
                            self.nodesmgr.dump_data()
                            self.counter = 1
                    else:
                        logger.error("update data failure.")
                except Exception, ex:
                    logger.error("%s:%s" % (sys._getframe().f_code.co_name, ex))
                time.sleep(1)
        except Exception, ex:
            logger.error("%s:%s" % (sys._getframe().f_code.co_name, ex))
        
    def stop(self):
        try:
            #stop collector thread
            self.collector.stop()
            self.collector.join()
            
            #stop reporter thread
            self.reporter.stop()
            self.reporter.join()
            
            #stop monitor self
            self.running = False
        except Exception, ex:
            logger.error("%s:%s" % (sys._getframe().f_code.co_name, ex))
        
        
        
